/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#ifndef NEWFRAMEWORKTEST_COMMONJOB_H
#define NEWFRAMEWORKTEST_COMMONJOB_H

#include <memory>
#include <atomic>
#include <unordered_set>
#include <boost/format.hpp>
#include "BasicJob.h"
#include "JobCommonInfo.h"
#include "JobMgr.h"
#include "error.h"
#include "ApplicationProtectPlugin_types.h"
#include "ApplicationProtectBaseDataType_types.h"
#include "ApplicationProtectFramework_types.h"
#include "log/Log.h"
#include "device_access/ControlDevice.h"
#include "replication/NasReplicationService.h"
#include "device_access/k8s/K8sutil.h"
#include "constant/ErrorCodes.h"
#include "job/ChannelManager.h"

enum class RestoreLocation {
    ORIGINAL_AND_SAMEFILESYTEM = 0,
    ORIGINAL_AND_DIFFFILESYTEM = 1,
    NEWPOS_AND_DIFFFILESYTEM = 2,
};

struct ReplicationProtectObjectExtendInfo {
    std::string tenantName {};
    std::string fileSystemId {};
    std::string usedCapacity {};
    std::string onlineStatus {};
    std::string tenantId {};
    std::string capacity {};

    BEGIN_SERIAL_MEMEBER
    SERIAL_MEMBER_TO_SPECIFIED_NAME(tenantName, tenantName)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(fileSystemId, fileSystemId)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(usedCapacity, usedCapacity)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(onlineStatus, onlineStatus)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(tenantId, tenantId)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(capacity, capacity)
    END_SERIAL_MEMEBER
};

struct ReplicationTargetObjectExtendInfo {
    std::string tenantName {};
    std::string fileSystemId {};
    std::string usedCapacity {};
    std::string onlineStatus {};
    std::string tenantId {};
    std::string capacity {};

    BEGIN_SERIAL_MEMEBER
    SERIAL_MEMBER_TO_SPECIFIED_NAME(tenantName, tenantName)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(fileSystemId, fileSystemId)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(usedCapacity, usedCapacity)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(onlineStatus, onlineStatus)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(tenantId, tenantId)
    SERIAL_MEMBER_TO_SPECIFIED_NAME(capacity, capacity)
    END_SERIAL_MEMEBER
};
class ReplicationCommonService : public BasicJob {
public:
    ReplicationCommonService() {};
    ~ReplicationCommonService() {};
    EXTER_ATTACK int PrerequisiteJob() override;
    EXTER_ATTACK int GenerateSubJob() override;
    EXTER_ATTACK int ExecuteSubJob() override;
    EXTER_ATTACK int PostJob() override;
    EXTER_ATTACK int CheckBackupJobType();
    EXTER_ATTACK int AllowBackupInLocalNode();

    struct RemotePath {
        std::string path {};
        int32_t type {0};

        BEGIN_SERIAL_MEMEBER
        SERIAL_MEMBER_TO_SPECIFIED_NAME(path, path)
        SERIAL_MEMBER_TO_SPECIFIED_NAME(type, type)
        END_SERIAL_MEMEBER
    };

    struct ProductExtendInfo {
        std::string fileSystemId {};
        std::string productEsn {};

        BEGIN_SERIAL_MEMEBER
        SERIAL_MEMBER_TO_SPECIFIED_NAME(fileSystemId, fileSystemId)
        SERIAL_MEMBER_TO_SPECIFIED_NAME(productEsn, productEsn)
        END_SERIAL_MEMEBER
    };

    struct ApplicationEnvRepIp {
        std::string name;
        std::string ipv4addr;

        BEGIN_SERIAL_MEMEBER
        SERIAL_MEMBER_TO_SPECIFIED_NAME(name, NAME)
        SERIAL_MEMBER_TO_SPECIFIED_NAME(ipv4addr, IPV4ADDR)
        END_SERIAL_MEMEBER
    };

    struct ApplicationEnvExtent {
        std::string verifyStatus {};
        std::string snapConsistency {};
        std::string managerIPs;
        std::string wwn {};

        BEGIN_SERIAL_MEMEBER
            SERIAL_MEMBER_TO_SPECIFIED_NAME(verifyStatus, verifyStatus)
            SERIAL_MEMBER_TO_SPECIFIED_NAME(snapConsistency, snapConsistency)
            SERIAL_MEMBER_TO_SPECIFIED_NAME(managerIPs, managerIPs)
            SERIAL_MEMBER_TO_SPECIFIED_NAME(wwn, wwn)
        END_SERIAL_MEMEBER
    };

    struct EnvAuthExtendInfo {
        std::string fingerPrint {};

        BEGIN_SERIAL_MEMEBER
            SERIAL_MEMBER_TO_SPECIFIED_NAME(fingerPrint, fingerPrint)
        END_SERIAL_MEMEBER
    };

    std::string m_productFSID = "";
    std::string m_pairID = "";
    std::string m_basicFSID = "";
    std::string m_snapshotName = "";
    std::string m_snapshotId = "";
    uint64_t m_qos = 0;
    uint64_t m_speedSamplingTimes = 0;
    uint64_t m_avgSpeed = 0;
    uint64_t m_totalSpeed = 0;
    uint64_t m_curProcess = 0;
    uint64_t m_usedCapacity = 0;
    time_t m_satrtTransTime = 0;
    bool m_isReportData = false; // 同构备份上报数据量的开关
    bool m_isBackUpFlow = false; // 是否是同构的备份流
    std::string m_productEsn; // 生产设备的ESN
    std::string m_basicEsn; // 二级存储的ESN
    std::string m_productManageIps = ""; // 记录生产端管理IP列表，逗号分隔, 用于
    AppProtect::SubJobStatus::type m_curJobstatus = AppProtect::SubJobStatus::RUNNING;
    std::unique_ptr<NasRepServiceObjOp::NasReplicationService> m_nasReplicationServiceObj = nullptr;
    std::shared_ptr<Module::DoradoNas> m_localDeviceController = nullptr;
    std::shared_ptr<Module::DoradoNas> m_remoteDeviceController = nullptr;
    virtual bool InitDeviceInfo() = 0;
    virtual bool PreStartTask() = 0;
    virtual void CleanTask(AppProtect::JobResult::type status) = 0;
    virtual bool UpdateBasicDeviceInfo(Module::ControlDeviceInfo &basicDeviceInfo) = 0;
    virtual bool UpdateProductDeviceInfo(Module::ControlDeviceInfo &productDeviceInfo) = 0;
    virtual int PostJobInner() = 0;
    virtual bool InitializeTask() = 0;
    virtual bool CheckAndCreatePair() = 0;
    bool StartTask(std::shared_ptr<Module::DoradoNas>& localController);
    void CalculateReplicationProgressAndSpeed(std::shared_ptr<Module::DoradoNas>& localController,
        const uint16_t& previousTaskProgress, const Module::ReplicationPairInfo& replicationPairInfo);
    int64_t RemotePairMachineProc(std::shared_ptr<Module::DoradoNas>& localController,
        std::shared_ptr<Module::DoradoNas>& remoteController, const Module::ReplicationPairInfo &replicationPairInfo,
        uint16_t &retryTimes);
    int64_t MonitorTask(std::shared_ptr<Module::DoradoNas>& localController,
                                    std::shared_ptr<Module::DoradoNas>& remoteController);
    bool UpdateDeviceAvilableIP(Module::ControlDeviceInfo &deviceInfo, const std::vector<std::string> &mgrIpList);
    bool IsReportAgentErrorCode(LogDetail logDetail);
    int GetContainerDoradoIp(std::string& innerDoradoIp);
    int GenerateSubJobInner();
    void KeepPluginAlive();
    int PrerequisiteJobInner();
    int ExecuteSubJobInner();
    bool AfterInitializeTask();
    bool MonitorExistSnapshotRevert(int64_t &errorCode);
    bool SwitchOverPrimaryAndSecondResource(std::shared_ptr<Module::DoradoNas>& deviceController,
        const std::string& pairID);
    void MonitorJobThread(int time);
    virtual bool CertVerifyMgr(const AppProtect::ApplicationEnvironment& protectEnv,
        Module::ControlDeviceInfo& productDeviceInfo);
    virtual bool RemoveCertification(const AppProtect::ApplicationEnvironment& protectEnv);
    int64_t WaitingOtherReplicationPairComplete(std::shared_ptr<Module::DoradoNas>& localController,
        std::shared_ptr<Module::DoradoNas>& remoteController);
    std::atomic<bool> m_connecting { false };
    uint64_t m_reportCount = 0;
    void RemoveSubJobFromChannelMgr();
    void AddSubJobToChannelMgr();

protected:
    bool GetMgrIpFromExt(std::vector<std::string>& ipList, const std::string& extInfo);
    bool GetRepIpFromExt(const std::string& extInfo);
protected:
    std::unordered_set<std::string> m_selectedRepNameList {}; // 从页面上选择的复制逻辑端口
    std::string m_capacityPath {};
    int64_t m_dataSize = 0;  // 缩减前数据量

private:
    std::atomic<bool> m_generateSubjobFinish { false };
    void SetDataSizeForJobDetail(SubJobDetails &subJobDetails);
    bool ActiveReplicationPair(std::shared_ptr<Module::DoradoNas>& localController);
    bool StartMonitorTask(std::shared_ptr<Module::DoradoNas>& localController,
        std::shared_ptr<Module::DoradoNas>& remoteController);
    void DeleteUsedCapacityResource();
};
#endif // NEWFRAMEWORKTEST_COMMONJOB_H
